package org.lanqiao.tjut.myUtils;

import java.io.File;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.converters.ByteConverter;
import org.apache.commons.beanutils.converters.DoubleConverter;
import org.apache.commons.beanutils.converters.FloatConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.commons.beanutils.converters.ShortConverter;

public class MyUtils {

	/**
	 * 将Request参数转换为实体bean 
	 * 要求：表单控件的name属性的值必须要和实体类的属性名一样（区分大小写） 具有文件上传处理功能
	 * @param request
	 *            request对象
	 * @param clazzBean
	 *            被转换的实体类类型
	 * @param fileUploadPath
	 *            文件上传服务器路径 例如："uploadfiles/stuImgs/" 不进行文件上传处理，赋值 null
	 * @param filePrefix
	 *            上传文件的前缀 文件名格式：文件前缀_UUID随机码.文件后缀
	 *            例如："admin_9d6ea285-09d9-4774-8cf3-7e898d7a0c53.png"
	 *            不进行文件上传处理，赋值 null
	 * @return 转换之后的实体类类型
	 */
	public static <T> T convertRequest2Bean(HttpServletRequest request, Class<T> clazzBean, 
			String fileUploadPath, String filePrefix) {
		T tb = null;
		// 注册日期转换器：request参数中的日期类型字符串值则会使用该转换器进行转换为Date类型
		ConvertUtils.register(new DateTimeConverter(), Date.class);
		/*
		 * 注册一下几个转换器：防止BeanUtils.setProperty()方法把null或者""的设值为0或者0.0
		 * 也就是：BeanUtils.setProperty()
		 * 给Integer、Short、Double、Float、Long、BigDecimal基本类型的值可以设置为null值，否则会设置默认值。
		 * 阻止BeanUtils.setProperty()方法把null值转换为默认值；
		 */
		ConvertUtils.register(new ByteConverter(null), Byte.class);
		ConvertUtils.register(new LongConverter(null), Long.class);
		ConvertUtils.register(new FloatConverter(null), Float.class);
		ConvertUtils.register(new ShortConverter(null), Short.class);
		ConvertUtils.register(new IntegerConverter(null), Integer.class);
		ConvertUtils.register(new DoubleConverter(null), Double.class);
		ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
		   
		try {
			tb = clazzBean.newInstance();
			T tb2 = clazzBean.newInstance();
			// ============除文件控件之外的表单参数的转换处理=============//
			// 获取所有的参数名
			Enumeration<String> strPNames = request.getParameterNames();
			// 循环遍历参数名，将获取到的参数值，赋值给实体bean
			if (strPNames != null) {
				while (strPNames.hasMoreElements()) {
					// 取出当前的参数名
					String pName = strPNames.nextElement();
					// 获取该元素的值
					String pVale = request.getParameter(pName);
					// 使用beanUtils给指定实体类的名字的属性进行赋值(注意日期类型需要进行转换处理)
					BeanUtils.setProperty(tb, pName, pVale);
				}
			}

			// ============文件控件表单转换处理以及文件上传处理=============//
			// 判定该表单中是否需要进行文件处理:
			/*
			 * 判定条件：
			 * request对象中的ContentType不能为null；
			 * ContentType中必须包含 multipart/form-data 属性值
			 */
			if (request.getContentType() != null
					&& request.getContentType().split(";")[0].equals("multipart/form-data")) {
				// 进行文件上传处理
				// 获取所有的part对象:包含普通控件对象和文件控件对象
				Collection<Part> parts = request.getParts();
				// 依次遍历每个part对象，找出文件类型的part进行文件上传处理
				for (Part part : parts) {
					// 获取文件控件的name属性的值
					String pName = part.getName();
					// 获取 MINE类型，普通控件的改属性是 null，文件上传控件的属性不是null
					String pContentType = part.getContentType();
					//System.out.println("part-ContenType:" + pContentType);
					// 判断当前的part是否是进行文件上传处理
					if (pContentType != null && !pContentType.equals("") && part.getSize() > 0) {
						// 进行文件上传处理
						// 处理文件对象part
						// 获取上传文件的文件名
						String strFileOldName = part.getSubmittedFileName();
						// 获取网站的根目录（相对于服务器的盘符）
						String realPath = request.getServletContext().getRealPath("/");

						// 验证该目录是否在服务器上存在，如果不存在则创建该目录
						File f = new File(realPath + fileUploadPath);
						if (!f.exists()) {
							f.mkdirs();
						}
						System.out.println("打印上传文件目录：" + f.getAbsolutePath());

						// 获取上传文件的后缀名
						String strFileType = strFileOldName.substring(strFileOldName.lastIndexOf('.'));
						// 创建上传文件名格式： 前缀_UUID随机编号.文件后缀
						String strUploadFileName = filePrefix + "_" + UUID.randomUUID() + strFileType;
						// 进行文件上传
						part.write(realPath + fileUploadPath + strUploadFileName);
						// 保存文件相对路径
						BeanUtils.setProperty(tb, pName, fileUploadPath + strUploadFileName);
					}
				}
			}
		} catch (Exception e) {
			// 获取实体类异常
			System.out.println("获取实体类异常：" + e.getMessage());
			e.printStackTrace();
		}

		return tb;
	}

	/**
	 * 将字符串转换为Integer类型
	 * 
	 * @param strVal
	 *            被转换的字符串
	 * @return 转换之后的Integer对象
	 */
	public static Integer convertString2Integer(String strVal) {
		if (strVal == null || strVal.equals("")) {
			return null;
		} else {
			return Integer.valueOf(strVal);
		}
	}

	/**
	 * 将日期类型转为指定格式的字符串
	 * 
	 * @param date
	 *            被转换的日期类型
	 * @param strPattern
	 *            日期格式串
	 * @return 转换之后的字符串(默认返回当前时间的字符串)
	 * 
	 */
	public static String convertDate2String(Date date, String strPattern) {
		// 如果时间对象为null则，返回当前时间
		if (date == null) {
			date = new Date();
		}
		// 如果格式串为空则使用默认格式
		if (strPattern == null || strPattern.equals("")) {
			// 默认格式串
			strPattern = "yyyy-MM-dd HH:mm:ss";
		}
		// 创建一个日期对象转换类
		SimpleDateFormat sdf = new SimpleDateFormat(strPattern);
		// 返回转换之后的字符串
		return sdf.format(date);
	}

	/**
	 * 将指定格式的字符串转换为日期类型 (strPattern的格式表示是strDate的格式)
	 * 
	 * @param strDate
	 *            日期字符串
	 * @param strPattern
	 *            日期字符串的格式(描述的是strDate的格式)
	 * @return 转换之后的日期对象(默认返回当前时间)
	 */
	public static Date convertString2Date(String strDate, String strPattern) {
		// 如果时间对象为null则，返回当前时间

		if (strDate == null || strDate.equals("")) {
			return new Date();
		}
		// 如果格式串为空则使用默认格式
		if (strPattern == null || strPattern.equals("")) {
			// 默认格式串
			strPattern = "yyyy-MM-dd HH:mm:ss";
		}
		// 创建一个日期对象转换类
		SimpleDateFormat sdf = new SimpleDateFormat(strPattern);
		// 返回转换之后的时间对象
		Date date = new Date();
		try {
			date = sdf.parse(strDate);
		} catch (ParseException e) {
			// 公用方法：字符串转换日期对象异常：
			// logRootLogger.error("公用方法-字符串转换日期对象异常：" + e.getMessage());
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * 获取某一个类的实例对象
	 * 
	 * @param clazz
	 *            获取实例对象的class
	 * @return 实例对象
	 */
	public static <T> T getNewInstance(Class<T> clazz) {
		T t = null;
		try {
			t = clazz.newInstance();
		} catch (Exception e) {
			// 公用方法：实例化对象异常
			System.out.println("公用方法：实例化对象异常:" + e.getMessage());
			e.printStackTrace();
		}
		return t;
	}

}
